package com.xiaoshuidi.cloud.module.finance.service.invoice.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fasterxml.jackson.core.type.TypeReference;
import com.xiaoshuidi.cloud.framework.common.exception.ServiceException;
import com.xiaoshuidi.cloud.framework.common.pojo.CommonResult;
import com.xiaoshuidi.cloud.framework.common.pojo.PageResult;
import com.xiaoshuidi.cloud.framework.common.util.json.JsonUtils;
import com.xiaoshuidi.cloud.framework.hangxin.core.dto.InvoicingItemDTO;
import com.xiaoshuidi.cloud.framework.hangxin.core.dto.InvoicingReqDTO;
import com.xiaoshuidi.cloud.framework.hangxin.core.dto.InvoicingRespDTO;
import com.xiaoshuidi.cloud.framework.hangxin.core.service.InvoiceService;
import com.xiaoshuidi.cloud.framework.mybatis.core.query.QueryWrapperX;
import com.xiaoshuidi.cloud.framework.redis.sequence.TimebaseSequenceGenerator;
import com.xiaoshuidi.cloud.framework.security.core.LoginUser;
import com.xiaoshuidi.cloud.framework.security.core.util.SecurityFrameworkUtils;
import com.xiaoshuidi.cloud.module.contract.api.ContractRentOrderApi;
import com.xiaoshuidi.cloud.module.contract.enums.bill.OrderPayStatusEnum;
import com.xiaoshuidi.cloud.module.contract.vo.CompanyInvoiceReqVO;
import com.xiaoshuidi.cloud.module.contract.vo.CompanyInvoiceRespVO;
import com.xiaoshuidi.cloud.module.contract.vo.OrderFeeDetailVO;
import com.xiaoshuidi.cloud.module.contract.vo.RentOrderExtVO;
import com.xiaoshuidi.cloud.module.finance.controller.admin.invoice.vo.FinanceInvoiceApprovalReqVO;
import com.xiaoshuidi.cloud.module.finance.controller.admin.invoice.vo.FinanceInvoiceCompanyApplyReqVO;
import com.xiaoshuidi.cloud.module.finance.controller.admin.invoice.vo.FinanceInvoiceRecordPageReqVO;
import com.xiaoshuidi.cloud.module.finance.controller.app.invoice.vo.AppFinanceInvoiceApplyReqVO;
import com.xiaoshuidi.cloud.module.finance.controller.app.invoice.vo.AppFinanceInvoicePageReqVO;
import com.xiaoshuidi.cloud.module.finance.convert.finance.InvoiceConvert;
import com.xiaoshuidi.cloud.module.finance.dal.dataobject.invoice.*;
import com.xiaoshuidi.cloud.module.finance.dal.mysql.invoice.FinanceInvoiceRecordItemMapper;
import com.xiaoshuidi.cloud.module.finance.dal.mysql.invoice.FinanceInvoiceRecordLogMapper;
import com.xiaoshuidi.cloud.module.finance.dal.mysql.invoice.FinanceInvoiceRecordMapper;
import com.xiaoshuidi.cloud.module.finance.dal.mysql.invoice.FinanceInvoiceRedRecordMapper;
import com.xiaoshuidi.cloud.module.finance.enums.finance.FinanceCustomerTypeEnum;
import com.xiaoshuidi.cloud.module.finance.enums.finance.SourceBizTypeEnum;
import com.xiaoshuidi.cloud.module.finance.enums.invoice.InvoicingStatusEnum;
import com.xiaoshuidi.cloud.module.finance.mq.producer.InvoiceQueryDelayProducer;
import com.xiaoshuidi.cloud.module.finance.service.invoice.FinanceInvoiceConfigService;
import com.xiaoshuidi.cloud.module.finance.service.invoice.FinanceInvoiceRecordService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

import static com.xiaoshuidi.cloud.module.finance.enums.ErrorCodeConstants.*;

@Service
public class FinanceInvoiceRecordServiceImpl implements FinanceInvoiceRecordService {
    @Resource
    private FinanceInvoiceRecordMapper financeInvoiceRecordMapper;
    @Resource
    private FinanceInvoiceRedRecordMapper financeInvoiceRedRecordMapper;
    @Resource
    private FinanceInvoiceRecordLogMapper financeInvoiceRecordLogMapper;
    @Resource
    private FinanceInvoiceRecordItemMapper financeInvoiceRecordItemMapper;
    @Resource
    private FinanceInvoiceConfigService financeInvoiceConfigService;
    @Resource
    private ContractRentOrderApi contractRentOrderApi;
    @Resource
    private TimebaseSequenceGenerator timebaseSequenceGenerator;
    @Resource
    private TransactionTemplate transactionTemplate;
    @Resource
    private InvoiceService invoiceService;
    @Resource
    private InvoiceQueryDelayProducer invoiceQueryDelayProducer;
    /**
     * 蓝票
     */
    private Integer BLUE = 1;
    /**
     * 红票
     */
    private Integer RED = 2;


    @Override
    public Long apply(LoginUser user, AppFinanceInvoiceApplyReqVO reqVO) {
        CommonResult<RentOrderExtVO> result = contractRentOrderApi.getById(reqVO.getOrderId());
        RentOrderExtVO vo = result.getCheckedData();

        if (!OrderPayStatusEnum.PAID.getCode().equals(vo.getPayStatus())) {
            throw new ServiceException(FINANCE_INVOICE_RENT_ORDER_UNPAID);
        }
        FinanceInvoiceConfigDO config = financeInvoiceConfigService.getByApartmentId(vo.getApartmentId());
        if (config == null) {
            throw new ServiceException(FINANCE_INVOICE_CONFIG_APARTMENT_NOT_FOUND);
        }
        List<FinanceInvoiceTaxRateDO> taxConfig = financeInvoiceConfigService.getFeeTax(config.getId());
        Map<Long, FinanceInvoiceTaxRateDO> taxMap = taxConfig.stream().collect(Collectors.toMap(FinanceInvoiceTaxRateDO::getFeeId, Function.identity()));

        BigDecimal amountWithoutTax = BigDecimal.ZERO;
        BigDecimal tax = BigDecimal.ZERO;
        for (OrderFeeDetailVO datum : vo.getFeeDetail()) {
            if (!reqVO.getFeeDetailIds().contains(datum.getId())) {
                continue;
            }
            // 只有配置的费项可开票
            if (taxMap.containsKey(datum.getFeeId())) {
                BigDecimal a = getAmountWithoutTax(datum.getAmount(),
                        taxMap.get(datum.getFeeId()).getTaxRate());
                // 租金优惠
                if (vo.getCouponDiscount() != null && vo.getCouponDiscount().compareTo(BigDecimal.ZERO) > 0
                        && datum.getFeeId() == 1) {
                    datum.setAmount(datum.getAmount().subtract(vo.getCouponDiscount()));
                    a = getAmountWithoutTax(datum.getAmount().subtract(vo.getCouponDiscount()), taxMap.get(datum.getFeeId()).getTaxRate());
                }
                amountWithoutTax = amountWithoutTax.add(a);
                tax = tax.add(datum.getAmount().subtract(a));
            }
        }

        FinanceInvoiceRecordDO record = FinanceInvoiceRecordDO.builder()
                .custId(user.getId())
                .custType(FinanceCustomerTypeEnum.INDIVIDUAL.name())
                .sourceBizId(reqVO.getOrderId().toString())
                .sourceBizType(SourceBizTypeEnum.RENT_ORDER.name())
                .apartmentId(vo.getApartmentId())
                .apartmentName(vo.getApartmentName())
                .roomName(vo.getRoomName())
                .invoiceType("电子普票")
                .titleType("个人")
                .title(reqVO.getTitle())
                .amount(vo.getTotalAmount())
                .invoicingCompany(config.getCompanyName())
                .invoiceConfigId(config.getId())
                .orderNo(vo.getOrderNo())
                .seqNo("FP" + timebaseSequenceGenerator.YYYYMMDDHHMMSS.next("lease:invoice:seq"))
                .amountWithoutTax(amountWithoutTax)
                .taxAmount(tax)
                .status(InvoicingStatusEnum.WAITING.name())
                .email(reqVO.getEmail())
                .mobile(reqVO.getMobile())
                .build();
        // 个人开票不需要审核
        if (!config.getPersonApplyApproval()) {
            record.setReviewer("系统自动");
        } else {
            record.setReviewer(config.getReviewer());
            record.setStatus(InvoicingStatusEnum.PENDING.name());
        }
        List<FinanceInvoiceRecordItemDO> items = vo.getFeeDetail().stream()
                .filter(f -> f.getAmount().compareTo(BigDecimal.ZERO) > 0)
                .filter(f -> taxMap.containsKey(f.getFeeId()))
                .map(f -> {
                    FinanceInvoiceTaxRateDO taxDo = taxMap.get(f.getFeeId());
                    return getFinanceInvoiceRecordItem(taxDo, f.getFeeId(), f.getAmount());
                }).collect(Collectors.toList());
        return transactionTemplate.execute(status -> {
            financeInvoiceRecordMapper.insert(record);
            items.forEach(i -> i.setRecordId(record.getId()));
            financeInvoiceRecordItemMapper.insertBatch(items);
            FinanceInvoiceRecordLogDO log = createLog(record.getId(), BLUE, "租客", "申请开票", "电子普票", null);
            financeInvoiceRecordLogMapper.insert(log);
            if (!config.getPersonApplyApproval()) {
                callApi(record, items, config);
            }
            return record.getId();
        });
    }

    private FinanceInvoiceRecordItemDO getFinanceInvoiceRecordItem(FinanceInvoiceTaxRateDO taxDo, Long feeId,
                                                                   BigDecimal amount) {
        // 不含税金额 = 含税金额/(1+税率) 四舍五入
        BigDecimal unitAmount = amount.divide(BigDecimal.ONE.add(taxDo.getTaxRate()), 6, RoundingMode.HALF_UP);
        // 税额 = 含税金额 - 不含税金额
        BigDecimal tax1 = amount.subtract(unitAmount.setScale(2, RoundingMode.HALF_UP));
        return FinanceInvoiceRecordItemDO.builder()
                .type(BLUE)
                .name(taxDo.getName())
                .feeId(feeId)
                .feeName(taxDo.getName())
                .goodsName(taxDo.getGoodsName())
                .num(1)
                .unitAmount(unitAmount)
                .totalAmount(unitAmount)
                .taxRate(taxDo.getTaxRate())
                .tax(tax1)
                .taxCategoryNo(taxDo.getTaxCategoryNo())
                .createTime(LocalDateTime.now())
                .build();
    }

    @Override
    public void approve(FinanceInvoiceApprovalReqVO reqVO) {
        FinanceInvoiceRecordDO financeInvoiceRecordDO = financeInvoiceRecordMapper.selectById(reqVO.getId());
        if (financeInvoiceRecordDO == null) {
            throw new ServiceException(FINANCE_INVOICE_RECORD_NOT_CONFIG);
        }
        if (!InvoicingStatusEnum.PENDING.name().equals(financeInvoiceRecordDO.getStatus())) {
            throw new ServiceException(FINANCE_INVOICE_RECORD_NOT_PENDING);
        }
        FinanceInvoiceRecordDO update = FinanceInvoiceRecordDO.builder()
                .id(reqVO.getId())
                .status(reqVO.getApprove() ? InvoicingStatusEnum.WAITING.name()
                        : InvoicingStatusEnum.REJECT.name())
                .build();
        FinanceInvoiceRecordLogDO log = createLog(reqVO.getId(), reqVO.getType(),
                SecurityFrameworkUtils.getLoginUser().getNickname(),
                "审核开票", reqVO.getApprove() ? "审核通过" : "审核拒绝", reqVO.getRemark());
        transactionTemplate.executeWithoutResult(status -> {
            financeInvoiceRecordMapper.updateById(update);
            financeInvoiceRecordLogMapper.insert(log);
            callApi(financeInvoiceRecordDO);
        });
    }

    private TypeReference<HashMap<String, Object>> mapTypeRef = new TypeReference<HashMap<String, Object>>() {
    };


    @Override
    public void companyApply(FinanceInvoiceCompanyApplyReqVO reqVO) {
        List<FinanceInvoiceTaxRateDO> l = financeInvoiceConfigService.getFeeTax(reqVO.getInvoiceConfigId());
        CompanyInvoiceReqVO reqVO1 = InvoiceConvert.INSTANCE.convert(reqVO);
        // 可开票费用
        if (reqVO.getInvoiceFeeType() == 1) {
            reqVO1.setFeeIds(Collections.singletonList(1L));
        } else {
            reqVO1.setFeeIds(l.stream().map(FinanceInvoiceTaxRateDO::getFeeId)
                    .filter(f -> f != 1L)
                    .collect(Collectors.toList()));
        }
        if (CollectionUtils.isEmpty(reqVO1.getFeeIds())) {
            throw new ServiceException(FINANCE_INVOICE_RENT_ORDER_FEE_NO_CONFIG);
        }
        // 可开票费用明细
        CommonResult<List<CompanyInvoiceRespVO>> result = contractRentOrderApi.getCompanyInvoiceableOrder(reqVO1);
        if (!result.isSuccess() || CollectionUtils.isEmpty(result.getData())) {
            throw new ServiceException(FINANCE_INVOICE_RENT_ORDER_FEE_NO_FOUND);
        }
        // 税号配置
        FinanceInvoiceConfigDO config = financeInvoiceConfigService.getById(reqVO.getInvoiceConfigId());
        CompanyInvoiceRespVO vo = result.getData().get(0);
        // 可开票金额
        BigDecimal invoiceableAmount = result.getData().stream().map(CompanyInvoiceRespVO::getInvoiceableAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
        // 税率配置map
        Map<Long, FinanceInvoiceTaxRateDO> map = l.stream().collect(Collectors.toMap(FinanceInvoiceTaxRateDO::getFeeId, Function.identity(), (a, b) -> b));
        // 可开票明细按费项分组
        Map<Long, List<CompanyInvoiceRespVO>> gmap = result.getData().stream().collect(Collectors.groupingBy(CompanyInvoiceRespVO::getFeeId));
        // 不含税总额
        BigDecimal amountWithoutTax = BigDecimal.ZERO;
        // 税额
        BigDecimal tax = BigDecimal.ZERO;
        List<FinanceInvoiceRecordItemDO> items = new ArrayList<>();
        // 生成发票明细
        for (Map.Entry<Long, List<CompanyInvoiceRespVO>> e : gmap.entrySet()) {
            if (map.containsKey(e.getKey())) {
                BigDecimal a = e.getValue().stream().map(CompanyInvoiceRespVO::getInvoiceableAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
                FinanceInvoiceRecordItemDO item = getFinanceInvoiceRecordItem(map.get(e.getKey()), e.getKey(), a);
                amountWithoutTax = amountWithoutTax.add(item.getUnitAmount());
                tax = tax.add(item.getTax());
                items.add(item);
            }
        }

        FinanceInvoiceRecordDO record = FinanceInvoiceRecordDO.builder()
                .custId(reqVO.getCompanyId())
                .custType(FinanceCustomerTypeEnum.COMPANY.name())
                .sourceBizId(vo.getOrderNo())
                .sourceBizType(SourceBizTypeEnum.COMPANY_RENT_ORDER.name())
                .taxpayerId(reqVO.getTaxpayerId())
                .extra(JsonUtils.getObjectMapper().convertValue(reqVO, mapTypeRef))
                .apartmentId(reqVO.getApartmentId())
                .apartmentName(vo.getApartmentName())
                .roomName(vo.getRoomName())
                .invoiceType(reqVO.getInvoiceType() == 1 ? "电子普票" : "电子专票")
                .titleType("企业")
                .title(reqVO.getCompanyName())
                .amount(invoiceableAmount)
                .invoicingCompany(config.getCompanyName())
                .invoiceConfigId(config.getId())
                .orderNo(vo.getOrderNo())
                .seqNo("FP" + timebaseSequenceGenerator.YYYYMMDDHHMMSS.next("lease:invoice:seq"))
                .amountWithoutTax(amountWithoutTax)
                .taxAmount(tax)
                .status(InvoicingStatusEnum.WAITING.name())
                .build();
        // 企业开票不需要审核
        if (!config.getCompanyApplyApproval()) {
            record.setReviewer("系统自动");
        } else {
            record.setReviewer(config.getReviewer());
            record.setStatus(InvoicingStatusEnum.PENDING.name());
        }
        transactionTemplate.execute(status -> {
            financeInvoiceRecordMapper.insert(record);
            items.forEach(i -> i.setRecordId(record.getId()));
            financeInvoiceRecordItemMapper.insertBatch(items);
            FinanceInvoiceRecordLogDO log = createLog(record.getId(), BLUE, SecurityFrameworkUtils.getLoginUser().getNickname(),
                    "申请开票", record.getInvoiceType(), null);
            financeInvoiceRecordLogMapper.insert(log);
            if (!config.getCompanyApplyApproval()) {
                callApi(record, items, config, reqVO);
            }
            CommonResult<Void> r = contractRentOrderApi.setInvoiceRecordId(record.getId(), result.getData().stream()
                    .map(CompanyInvoiceRespVO::getFeeDataId).collect(Collectors.toList()));
            r.getCheckedData();
            return record.getId();
        });
    }


    @Override
    public PageResult<FinanceInvoiceRecordDO> getPage(FinanceInvoiceRecordPageReqVO reqVO) {
        QueryWrapperX<FinanceInvoiceRecordDO> qw = new QueryWrapperX<>();
        if (reqVO.getCreateDate() != null && reqVO.getCreateTime().length == 1) {
            qw.eq("create_date", reqVO.getCreateDate()[0]);
        }
        if (reqVO.getCreateDate() != null && reqVO.getCreateTime().length > 1) {
            qw.between("create_date", reqVO.getCreateTime()[0], reqVO.getCreateTime()[1]);
        }
        if (reqVO.getCreateTime() != null && reqVO.getCreateTime().length == 1) {
            qw.eq("create_time", reqVO.getCreateTime()[0]);
        }
        if (reqVO.getCreateTime() != null && reqVO.getCreateTime().length > 1) {
            qw.between("create_time", reqVO.getCreateTime()[0], reqVO.getCreateTime()[1]);
        }
        if (StringUtils.hasText(reqVO.getKeyword())) {
            qw.and(qw1 -> qw1.like("invoice_no", reqVO.getKeyword())
                    .or()
                    .like("invoice_code", reqVO.getKeyword())
                    .or()
                    .like("title", reqVO.getKeyword()));
        }

        return financeInvoiceRecordMapper.selectPage(reqVO, qw.eq(StringUtils.hasText(reqVO.getInvoiceType()), "invoice_type", reqVO.getInvoiceType())
                .eq(StringUtils.hasText(reqVO.getStatus()), "status", reqVO.getStatus())
                .eq(reqVO.getInvoiceConfigId() != null, "invoice_config_id", reqVO.getInvoiceConfigId())
        );
    }

    @Override
    public FinanceInvoiceRecordDO getById(Long id) {
        return financeInvoiceRecordMapper.selectById(id);
    }

    @Override
    public List<FinanceInvoiceRecordItemDO> getItems(Long id) {
        return financeInvoiceRecordItemMapper.selectList("record_id", id);
    }

    @Override
    public PageResult<FinanceInvoiceRecordDO> getPage(AppFinanceInvoicePageReqVO reqVO) {
        return financeInvoiceRecordMapper.selectPage(reqVO, new QueryWrapper<FinanceInvoiceRecordDO>()
                .eq(StringUtils.hasText(reqVO.getStatus()), "status", reqVO.getStatus())
                .eq("cust_id", reqVO.getCustId())
                .eq("cust_type", reqVO.getCustType()));
    }

    /**
     * 开票操作日志
     *
     * @param recordId 开票记录
     * @param type     1蓝票2红票
     * @param operator
     * @param stage    步骤
     * @param content  内容
     * @param remark   备注
     * @return
     */
    private FinanceInvoiceRecordLogDO createLog(Long recordId, Integer type, String operator,
                                                String stage, String content, String remark) {
        return FinanceInvoiceRecordLogDO.builder()
                .recordId(recordId)
                .type(type)
                .operator(operator)
                .stage(stage)
                .content(content)
                .remark(remark)
                .build();
    }

    @Override
    public void callApi(FinanceInvoiceRecordDO record) {
        List<FinanceInvoiceRecordItemDO> items = financeInvoiceRecordItemMapper.selectList("record_id", record.getId());
        FinanceInvoiceConfigDO config = financeInvoiceConfigService.getById(record.getInvoiceConfigId());
        InvoicingReqDTO reqDTO;
        if ("企业".equals(record.getInvoiceType())) {
            FinanceInvoiceCompanyApplyReqVO reqVO = JsonUtils.getObjectMapper().convertValue(record.getExtra(), FinanceInvoiceCompanyApplyReqVO.class);
            reqDTO = convert(record, items, config, reqVO);
        } else {
            reqDTO = convert(record, items, config);
        }
        callApi(reqDTO);
    }

    @Override
    public FinanceInvoiceRecordDO getBySeqNo(String seqNo) {
        return financeInvoiceRecordMapper.selectOne("seq_no", seqNo);
    }

    @Override
    public void updateById(FinanceInvoiceRecordDO build) {
        financeInvoiceRecordMapper.updateById(build);
    }

    @Override
    public InvoicingRespDTO query(Long id) {
        FinanceInvoiceRecordDO record = financeInvoiceRecordMapper.selectById(id);
        if (record == null) {
            throw new ServiceException(FINANCE_INVOICE_NOT_EXISTS);
        }
        FinanceInvoiceConfigDO config = financeInvoiceConfigService.getById(record.getInvoiceConfigId());
        return invoiceService.query(config.getCompanyTaxpayerId(), config.getHangxinAuthCode(), record.getSeqNo());
    }

    private void callApi(FinanceInvoiceRecordDO record, List<FinanceInvoiceRecordItemDO> items,
                         FinanceInvoiceConfigDO config) {
        callApi(convert(record, items, config));
    }

    private void callApi(FinanceInvoiceRecordDO record, List<FinanceInvoiceRecordItemDO> items,
                         FinanceInvoiceConfigDO config, FinanceInvoiceCompanyApplyReqVO reqVO) {
        callApi(convert(record, items, config, reqVO));
    }

    private void callApi(InvoicingReqDTO reqDTO) {
        invoiceService.apply(reqDTO);
        invoiceQueryDelayProducer.send(reqDTO.getFPQQLSH());
    }

    private DecimalFormat decimalFormat = new DecimalFormat("#0.00");

    private InvoicingReqDTO convert(FinanceInvoiceRecordDO record, List<FinanceInvoiceRecordItemDO> items, FinanceInvoiceConfigDO config, FinanceInvoiceCompanyApplyReqVO reqVO) {
        InvoicingReqDTO reqDTO = convert(record, items, config);
        reqDTO.setGMF_NSRSBH(record.getTaxpayerId());
        reqDTO.setGMF_MC(record.getTitle());
        reqDTO.setGMF_DZDH(reqVO.getAddress() + reqVO.getPhone());
        reqDTO.setGMF_YHZH(reqVO.getBankAccount());
        // 81电子专票 其它电子普票
        reqDTO.setFPZL(reqVO.getInvoiceType() == 2 ? "81" : "82");
        return reqDTO;
    }

    private InvoicingReqDTO convert(FinanceInvoiceRecordDO record, List<FinanceInvoiceRecordItemDO> items, FinanceInvoiceConfigDO config) {
        InvoicingReqDTO reqDTO = new InvoicingReqDTO();
        reqDTO.setAuthorizationCode(config.getHangxinAuthCode());
        reqDTO.setTaxpayerId(config.getCompanyTaxpayerId());
        reqDTO.setFPQQLSH(record.getSeqNo());
        reqDTO.setDDH(record.getOrderNo());
        // 0蓝票1红票
        reqDTO.setKPLX("0");
        reqDTO.setBMB_BBH("33.0");
        reqDTO.setXSF_NSRSBH(config.getCompanyTaxpayerId());
        reqDTO.setXSF_MC(config.getCompanyName());
        reqDTO.setXSF_DZDH(config.getAddress() + config.getPhone());
        reqDTO.setXSF_YHZH(config.getBankAccount());
        reqDTO.setGMF_MC(record.getTitle());
        reqDTO.setKPR(config.getDrawer());
        reqDTO.setSKR(config.getPayee());
        reqDTO.setFHR(config.getReviewer());
        reqDTO.setJSHJ(decimalFormat.format(record.getAmount()));
        reqDTO.setHJJE(decimalFormat.format(record.getAmountWithoutTax()));
        reqDTO.setHJSE(decimalFormat.format(record.getTaxAmount()));
        // 81电子专票 其它电子普票
        reqDTO.setFPZL("82");
        reqDTO.setItems(items.stream().map(i -> {
            InvoicingItemDTO item = new InvoicingItemDTO();
            // 发票性质行
            item.setFPHXZ("0");
            item.setXMMC(i.getName());
            item.setGGXH(i.getSpecName());
            item.setDW(i.getUnit());
            item.setXMSL(i.getNum().toString());
            item.setXMDJ(decimalFormat.format((i.getUnitAmount())));
            item.setXMJE(decimalFormat.format(i.getTotalAmount()));
            item.setSL(decimalFormat.format(i.getTaxRate()));
            item.setSE(decimalFormat.format(i.getTax()));
            item.setSPBM(i.getTaxCategoryNo());
            item.setYHZCBS("0");
            return item;
        }).collect(Collectors.toList()));
        return reqDTO;
    }

    /**
     * 不含税金额 = 含税金额/(1+税率)
     * 税额= 含税金额 - 不含税金额
     *
     * @return
     */
    private BigDecimal getAmountWithoutTax(BigDecimal amount, BigDecimal taxRate) {
        return amount.divide(BigDecimal.ONE.add(taxRate), 6, RoundingMode.HALF_UP);
    }
}
